<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width">

    <title>Script processor node example</title>

    <link rel="stylesheet" href="">
    <!--[if lt IE 9]>
      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
  </head>

  <body>
    <h1>ScriptProcessorNode example</h1>

    <button>Play song</button>

    <pre></pre>
    <script>
      const myScript = document.querySelector('script');
      const myPre = document.querySelector('pre');
      const playButton = document.querySelector('button');

      // Create AudioContext and buffer source
      let audioCtx;
      let source;

      function init() {
        audioCtx = new AudioContext();
        source = audioCtx.createBufferSource();

        // Create a ScriptProcessorNode with a bufferSize of 4096 and a single input and output channel
        let scriptNode = audioCtx.createScriptProcessor(4096, 1, 1);
        console.log(scriptNode.bufferSize);

        // load in an audio track via XHR and decodeAudioData

        function getData() {
          request = new XMLHttpRequest();
          request.open('GET', 'viper.ogg', true);
          request.responseType = 'arraybuffer';
          request.onload = function() {
            let audioData = request.response;

            audioCtx.decodeAudioData(audioData, function(buffer) {
            myBuffer = buffer;
            source.buffer = myBuffer;
          },
            function(e){"Error with decoding audio data" + e.err});
          }
          request.send();
        }

        // Give the node a function to process audio events
        scriptNode.onaudioprocess = function(audioProcessingEvent) {
          // The input buffer is the song we loaded earlier
          let inputBuffer = audioProcessingEvent.inputBuffer;

          // The output buffer contains the samples that will be modified and played
          let outputBuffer = audioProcessingEvent.outputBuffer;

          // Loop through the output channels (in this case there is only one)
          for (let channel = 0; channel < outputBuffer.numberOfChannels; channel++) {
                let inputData = inputBuffer.getChannelData(channel);
                let outputData = outputBuffer.getChannelData(channel);

                // Loop through the 4096 samples
                for (let sample = 0; sample < inputBuffer.length; sample++) {
                  // make output equal to the same as the input
                  outputData[sample] = inputData[sample];

                  // add noise to each output sample
                  outputData[sample] += ((Math.random() * 2) - 1) * 0.2;
                }
              }
        }

        getData();

        source.connect(scriptNode);
        scriptNode.connect(audioCtx.destination);
        source.start();

        // When the buffer source stops playing, disconnect everything
        source.onended = function() {
          source.disconnect(scriptNode);
          scriptNode.disconnect(audioCtx.destination);
        }

      }

      // wire up play button
      playButton.onclick = function() {
        if(!audioCtx) {
          init();
        }
      }

      //output the script into the pre element
      myPre.innerHTML = myScript.innerHTML;
    </script>
  </body>
</html>
